package week13.week_13_client;
import java.io.*;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;

import week13.week_13_server.Message;
import week13.week_13_server.MessageType;
import week13.week_13_server.MyUtils;
import week13.week_13_server.SecurityUtils;
import week13.week_13_server.Status;
import week13.week_13_server.User;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.PasswordField;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;


public class MyInitGUI extends Application {

	Button btn_register, btn_login;
	TextField tf_name;
	PasswordField pf;
	Stage initStage;
	SSLSocketFactory factory=null;
	SSLSocket s;
	User user;

	{
		try{
			//获取jks类型的密钥库，ks保存本主机的公钥和私钥的密钥库,tks是保存来访者的公钥的密钥库
			KeyStore ks = KeyStore.getInstance("JKS");//本机的密钥库
			KeyStore tks = KeyStore.getInstance("JKS");//可信任的其它来访主机的公钥库

			//加载密钥库文件，需要提供口令
			ks.load(new FileInputStream(ClientInfo.keyStorePath),ClientInfo.password_ks.toCharArray());
			tks.load(new FileInputStream(ClientInfo.trustStorePath),ClientInfo.password_ts.toCharArray());

			//为相应的密钥库创建一个KeyManagerFactory，TrustManagerFactory
			KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
			TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");

			kmf.init(ks,ClientInfo.password_pk.toCharArray());
			tmf.init(tks);

			//为使用的算法创建一个SSLContext,
			SSLContext context = SSLContext.getInstance("SSL");
			context.init(kmf.getKeyManagers(),tmf.getTrustManagers(), null);
			//context.init(null,tmf.getTrustManagers(), null);//如果服务器不需要验证客户端，则可以不用初始化客户的密钥库

			factory = context.getSocketFactory();
			System.out.println("Successful to load all the info to initiate client!");
		}catch (IOException | NoSuchAlgorithmException | CertificateException | KeyManagementException | KeyStoreException | UnrecoverableKeyException  e) {
			// TODO: handle exception
			e.printStackTrace();
		}
	}

	@Override
	public void start(Stage stage) throws Exception {
		initStage = stage;
		// TODO Auto-generated method stub
		Label lb_name = new Label("用户:");
		tf_name = new TextField();

		Label lb_passwd = new Label("密码：");
		pf = new PasswordField();

		btn_register = new Button("注册");
		btn_register.setOnAction(this::btnRegistHandler);
		btn_login = new Button("登录");
		btn_login.setOnAction(this::btnLoginHandler);
		GridPane gPane = new GridPane();
		gPane.setAlignment(Pos.CENTER);
		gPane.setPrefWidth(300);
		gPane.setPrefHeight(200);
		gPane.setVgap(30);
		gPane.setHgap(20);
		gPane.addRow(0, lb_name,tf_name);
		gPane.addRow(1, lb_passwd,pf);
		gPane.addRow(2, btn_register,btn_login);

		Scene scene = new Scene(gPane);
		stage.setTitle("简单的聊天程序，来自1707");
		stage.setScene(scene);
		stage.show();
	}

	public void btnLoginHandler(ActionEvent e){
		if(!login()) {
			return;
		}
		try {
			new LoginGUI(s,factory,user);//打开聊天窗口
			initStage.close();//关闭注册登录窗口
		} catch (Exception e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		};
	}

	public boolean login(){
		boolean result = false;
		try{
			s = (SSLSocket)factory.createSocket(ClientInfo.serverAddr, ClientInfo.serverPort);
			ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream());
			ObjectInputStream ois = new ObjectInputStream(s.getInputStream());
			System.out.println("Client is ready!");
			String passwd = SecurityUtils.getHash(pf.getText(), "MD5");//应用MD5加密密码
			User user = new User(tf_name.getText(), passwd);
			this.user=user;
			Message msg = new Message();
			msg.setMsgType(MessageType.MSG_LOG);
			msg.setContent(user);
			oos.writeObject(msg);
			oos.flush();
			System.out.println("sent: " + msg);
			msg=(Message)ois.readObject();
			System.out.println("received: " + msg);
			if(msg.getStatus()==Status.SUCCESS){
				result = true;
			} else {
				MyUtils.showAlert("登录失败，请重新登录！");
			}
		}catch (IOException | ClassNotFoundException e) {
			// TODO: handle exception
			e.printStackTrace();
		}
		return result;
	}

	public void btnRegistHandler(ActionEvent e){
		if(!register()) {
			return;
		}
		try {
			MyUtils.showAlert("注册成功，请登录");
		} catch (Exception e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		};
	}

	public boolean register(){
		boolean result = false;
		try(
			//创建SSL socket
			SSLSocket s = (SSLSocket)factory.createSocket(ClientInfo.serverAddr, ClientInfo.serverPort);
			//注意：先创建输出流对象，再创建输入流对象，服务器则相反
			ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream());
			ObjectInputStream ois = new ObjectInputStream(s.getInputStream());
		){
			System.out.println("Client is ready!");
			String passwd = SecurityUtils.getHash(pf.getText(), "MD5");//应用MD5加密密码
			User user = new User(tf_name.getText(), passwd);
			Message msg = new Message();
			msg.setMsgType(MessageType.MSG_REG);
			msg.setContent(user);
			oos.writeObject(msg);
			oos.flush();
			System.out.println("sent: " + msg);
			msg=(Message)ois.readObject();
			System.out.println("received: " + msg);
			if(msg.getStatus()==Status.SUCCESS){
				result = true;
			} else {
				MyUtils.showAlert("注册失败，请重新注册！");
			}
		}catch (IOException | ClassNotFoundException e) {
			// TODO: handle exception
			e.printStackTrace();
		}
		return result;
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Application.launch(args);
	}

}
